#pragma once

#include <tchar.h>
#include <strsafe.h>

//////////////////////////////////////////////////////////////////////////

#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define __LOC2__ __FILE__ "("__STR1__(__LINE__)") : "

#if _DEBUG
#define UAIBreakIn() _asm int 3;
#define FIXME __pragma(message(__LOC2__ "warning C701: You need Fix this part!"))
#define TESTME __pragma(message(__LOC2__ "warning C702: Please Test this part!"))
#else
#define UAIBreakIn()
#define FIXME
#define TESTME
#endif

FORCEINLINE 
void 
UAIpPrint(LPSTR text, ...)
{
    CHAR szString[MAX_PATH] = {0};

    va_list args;
    va_start(args, text);
    StringCchVPrintfA(szString, MAX_PATH, text, args);
    va_end(args);

    OutputDebugStringA(szString);
}

#if _DEBUG
#define UAIPrint(_Text_, ...) \
    UAIpPrint("[UAI][%s][%d]: " _Text_, __FUNCTION__, __LINE__, __VA_ARGS__)
#else
#define UAIPrint(_Text_, ...) 
#endif

#define UAIMustPrint(_Text_, ...) \
    UAIpPrint("[UAI][%s][%d]: " _Text_,  __FUNCTION__, __LINE__, __VA_ARGS__)

//////////////////////////////////////////////////////////////////////////

#define ARGUMENT_PRESENT(ArgumentPointer) \
    ((CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL))

//////////////////////////////////////////////////////////////////////////

// [Note] --> !!
//
// 1. AssertRetXXX normally are used to check input parameters.
// 2. Assert could be used inside a function.
//

#ifdef _DEBUG
#define AssertRet(_X_) assert(_X_)
#define AssertRetEx(_X_, _Ret_) assert(_X_)
#define Assert(_X_) assert(_X_)
#else
#define AssertRet(_X_) if(!(_X_)){return;}
#define AssertRetEx(_X_, _Ret_) if(!(_X_)){return(_Ret_);}
#define Assert(_X_) //
#endif

//////////////////////////////////////////////////////////////////////////

#define SafeVerify(_X_) _X_ && (ULONG)_X_ <= 0x7FFFFFFF

#define SafeDelete(_X_) if (SafeVerify(_X_)) { delete _X_; _X_ = NULL; } else { _X_ = NULL; }
#define SafeDeleteArray(_X_) if (SafeVerify(_X_)) { delete[] _X_; _X_ = NULL; } else { _X_ = NULL; }

//////////////////////////////////////////////////////////////////////////

#define Internal_DEBUG  1